package net.xiaoyu.target_lock.util;

import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.xiaoyu.target_lock.Config;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.client.event.MovementInputUpdateEvent;

public class TargetingUtils {

    public static void lockNearestEntity(Minecraft mc, LockTargetData lockData) {
        double lockRange = Config.LOCK_RANGE.get();
        Entity nearestEntity = EntityUtils.findNearestLivingEntity(mc, lockRange);
        
        if (nearestEntity != null) {
            lockData.setLockedTarget(nearestEntity);
            lockData.setTargetLocked(true);
            lockData.setLockedTargetPosition(null);
            MessageUtils.showLockSuccessMessage(mc, nearestEntity);
        } else {
            MessageUtils.showNoTargetsMessage(mc);
        }
    }

    public static void findAndLockNearestEntity(Minecraft mc, LockTargetData lockData) {
        double lockRange = Config.LOCK_RANGE.get();
        Entity nearestEntity = EntityUtils.findNearestLivingEntity(mc, lockRange);
        
        if (nearestEntity != null && nearestEntity != lockData.getLockedTarget()) {
            lockData.setLockedTarget(nearestEntity);
            lockData.setLockedTargetPosition(null);
            MessageUtils.showSwitchTargetMessage(mc, nearestEntity);
        }
    }

    public static void switchToNextNearestTarget(Minecraft mc, LockTargetData lockData) {
        double lockRange = Config.LOCK_RANGE.get();
        Entity nearestEntity = EntityUtils.findNearestLivingEntity(mc, lockRange, lockData.getLockedTarget());
        
        if (nearestEntity != null) {
            lockData.setLockedTarget(nearestEntity);
            lockData.setTargetLocked(true);
            lockData.setLockedTargetPosition(null);
            MessageUtils.showSwitchToNextTargetMessage(mc, nearestEntity);
        } else {
            lockData.reset();
            MessageUtils.showNoNextTargetMessage(mc);
        }
    }

    public static void handleInvalidTarget(Minecraft mc, LockTargetData lockData) {
        if (!lockData.getLockedTarget().isAlive()) {
            MessageUtils.showTargetKilledMessage(mc);

            if (Config.SWITCH_TO_NEXT_TARGET_AFTER_KILL.get() && Config.AUTO_SWITCH_TO_NEXT_TARGET.get()) {
                switchToNextNearestTarget(mc, lockData);
                return;
            } else {
                lockData.reset();
                return;
            }
        }

        lockData.reset();
        MessageUtils.showTargetLostMessage(mc);
    }

    public static void keepAttackRange(Player player, Entity target, MovementInputUpdateEvent event) {
        double distanceDiff = CombatUtils.getDistanceDiff(player, target);
        Vec3 directionToTarget = CombatUtils.getHorizontalDirectionToTarget(player, target);
        Vec3 moveDirection = CombatUtils.getMoveDirection(directionToTarget, distanceDiff);
        
        double adjustmentFactor = Math.abs(distanceDiff) * Config.ATTACK_RANGE_ADJUSTMENT_FACTOR.get();
        
        float[] moveImpulses = CombatUtils.calculateMoveImpulse(moveDirection, player.getYRot());
        
        event.getInput().forwardImpulse = moveImpulses[0] * (float) adjustmentFactor;
        event.getInput().leftImpulse = moveImpulses[1] * (float) adjustmentFactor;
    }

    public static void performAutoAttack(Player player, Entity target, Minecraft mc, double lockRangeSquared) {
        double distance = CombatUtils.getDistance(player, target);
        double attackRange = CombatUtils.getAttackRange(player);
        double distanceDiff = distance - attackRange;

        boolean shouldHighFrequencyAttack = distanceDiff <= 0 ?
        Config.HIGH_FREQUENCY_ATTACK_AT_CRITICAL_POINT.get() :
        Config.HIGH_FREQUENCY_ATTACK_NEAR_CRITICAL_POINT.get();

        if (shouldHighFrequencyAttack) {
            if (!Config.AUTO_ATTACK_WITHIN_RANGE.get()) {
                return;
            }
        } else {
            if (!Config.AUTO_ATTACK_AT_CRITICAL_POINT_POSITION.get()) {
                return;
            }
        }

        if (Config.AUTO_ATTACK_ALL_TARGETS_IN_RANGE.get()) {
            attackTargets(player, target, mc, lockRangeSquared, shouldHighFrequencyAttack, true);
        } else {
            attackTargets(player, target, mc, lockRangeSquared, shouldHighFrequencyAttack, false);
        }
    }

    private static void attackTargets(
        Player player, Entity target, Minecraft mc, 
        double lockRangeSquared, boolean shouldHighFrequencyAttack, boolean attackAllTargets
    ) {
        boolean canAttack = shouldHighFrequencyAttack || player.getAttackStrengthScale(0.0F) >= 1.0F;
        
        if (!canAttack) {
            return;
        }
        
        if (attackAllTargets) {
            if (mc.player != null && mc.level != null) {
                Vec3 playerPos = mc.player.getEyePosition();
                for (Entity entity : mc.level.entitiesForRendering()) {
                    if (entity != player && entity.isAlive() && entity instanceof LivingEntity) {
                        double entityDistance = entity.distanceToSqr(playerPos);
                        if (entityDistance <= lockRangeSquared) {
                            mc.gameMode.attack(player, entity);
                        }
                    }
                }
            }
        } else {
            mc.gameMode.attack(player, target);
        }
    }
}